#define _USE_MATH_DEFINES
#include <math.h>
#include "qdebug.h"
#include "visualisierung.h"
#include "qgridlayout.h"
#include <QTimer>
#include "qfile.h"

Visualisierung::Visualisierung() {
	setWindowTitle(tr("Visualization: Edge Bundling"));
	resize(1024,768);

	getData();
	initInterface();
}

Visualisierung::~Visualisierung() {
	qDeleteAll(airports.begin(), airports.end());
	airports.clear();

	qDeleteAll(routes.begin(), routes.end());
	routes.clear();

	delete input;
	delete renderWidget;
	delete mainWidget;
}


void Visualisierung::initInterface(void) {
	mainWidget = new QWidget(this);
	setCentralWidget(mainWidget);
	QGridLayout* layout = new QGridLayout(mainWidget);
	
	renderWidget = new RenderWidget(mainWidget, &graph);
	layout->addWidget(renderWidget, 0, 0);

	//initialize default values for widget drawing parameters: later specify all that stuff in GUI?
	//renderWidget->setBackgroundImage(QString("Resources/mercator_template.png"));
	renderWidget->setBackgroundImage(QString("Resources/mercator_projection.svg"));
	renderWidget->setNodeProperties(1.5, QColor(0xa6, 0xce, 0x39), Qt::black, 1);
	renderWidget->setEdgeProperties(QColor(0, 0, 0, 70), 1);
	renderWidget->drawNodes(true);
	renderWidget->drawEdges(true);
	renderWidget->wrapEdges(true);
}

void Visualisierung::getData(void) {
	input = new FileParser();

	bool success = true;

	success &= input->read("Resources/airports.dat", airports);
	qDebug() << airports.size() << "airports parsed.";

	success &= input->read("Resources/routes.dat", routes);
	qDebug() << routes.size() << "routes parsed.";

	if(success) 
		initEdges(airports, routes);
	else
		qDebug() << "Something went wrong!";
}

void Visualisierung::initEdges(QList<AirportEntry*> &airports, QList<RouteEntry*> &routes) {
	
	QList<int> airportIDs;
	for (QList<AirportEntry*>::iterator airportIter = airports.begin(); airportIter != airports.end(); ++airportIter) {
		AirportEntry* airport = *airportIter;

		//construct a list of all airport IDs in order to be able search for the indices in the next step
		airportIDs << airport->airport_ID;

		//initialize airport
		double longitude = airport->longitude;
		double latitude = airport->latitude;

		////Mercator projection of map points
		//normalized to [0; 1]-range
		double proj_y = log(tan(M_PI_4 * (1.0 + latitude / 90.0))); 
		double y = (1.0 - proj_y / M_PI) / 2.0;
		y = qMax(0.0, qMin(y, 1.0)); //projection is undefined for extreme values at the poles 

		double x = (1.0 + longitude / 180.0) / 2.0;   

		airport->setCoord(QPointF(x, y));
		graph.addNode(airport);
	}
	
	//iterate through all routes and find relevant origin and destination airports
	for (QList<RouteEntry*>::iterator routeIter = routes.begin(); routeIter != routes.end(); ++routeIter) {
		RouteEntry* route = *routeIter;

		int originPos = airportIDs.indexOf(route->origin_ID);
		int destinationPos = airportIDs.indexOf(route->destination_ID);

		if(originPos == -1 || destinationPos == -1) {
			qDebug() << "This should not happen anymore";
			continue;
		}

		AirportEntry* origin = airports[originPos];
		AirportEntry* destination = airports[destinationPos];

		origin->increment();
		destination->increment();

		//initialize edges
		route->addNode(origin);
		route->addNode(destination);
		graph.addEdge(route);
	}
}

void Visualisierung::initNode(AirportEntry* airport) {
	double longitude = airport->longitude;
	double latitude = airport->latitude;

	////Mercator projection of map points
	//normalized to [0; 1]-range
		
	double proj_y = log(tan(M_PI_4 * (1.0 + latitude / 90.0))); 
	double y = (1.0 - proj_y / M_PI) / 2.0;
	y = qMax(0.0, qMin(y, 1.0)); //projection is undefined for extreme values at the poles 

	double x = (1.0 + longitude / 180.0) / 2.0;   

	airport->setCoord(QPointF(x, y));
	airport->setInfo(QString(airport->getName() + ", " + airport->getCity() + ", " + airport->getCountry()));
	graph.addNode(airport);
}